#pragma once
#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"
#include <functional>
#include "InetAddr.hpp"
#include "Tool.hpp"
#include<sys/wait.h>
using namespace LogModel;
class Tcpserver
{

private:
    void Service(int fd, InetAddr &addr)
    {
        char buff[1024];
        while (true)
        {
            int size = read(fd, buff, sizeof(buff) - 1);
            if (size > 0)
            {
                buff[size] = 0;
                LOG(LogLevel::DEBUG) << addr.GetName() << "say:" << buff;
            }
            else if (size == 0)
            {
                LOG(LogLevel::DEBUG) << addr.GetName() << "退出了...";
                close(fd);
                break;
            }
            else
            {
                LOG(LogLevel::FATAL) << "异常";
                close(fd);
                exit(READ_ERR);
            }

            //服务器给客户端返回消息
            std::string send_buff="server say:";
            send_buff+=buff;
            int n = write(fd,send_buff.c_str(),send_buff.size());

        }
    }

public:
    Tcpserver(uint16_t port) : _port(port), _listensockfd(-1), _isruning(false)
    {
    }

    class Intent
    {
        public:
        Intent(InetAddr& addr,int fd,Tcpserver*tcp)
        :_addr(addr),
        _sockfd(fd),
        _tcp(tcp)
        {}
        InetAddr _addr;
        int _sockfd;
        Tcpserver *_tcp;
    };
    void Init()
    {

        // 1.创建监听描述符
        _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensockfd < 0)
        {
            LOG(LogLevel::FATAL) << "socket error";
            exit(SOCKET_ERR);
        }
        LOG(LogLevel::DEBUG) << "socket success" << _listensockfd;

        // 2.bind
        InetAddr server(_port);
        int n = bind(_listensockfd, server.Addr(), server.Getsize());
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "bind error";
            exit(BIND_ERR);
        }
        LOG(LogLevel::FATAL) << "socket success";

        // 3.建立监听
        int m = listen(_listensockfd, 5);
        if (m < 0)
        {
            LOG(LogLevel::FATAL) << "listen error";
            exit(LISTEN_ERR);
        }
        LOG(LogLevel::DEBUG) << "listen success";
    }

    static void* Router(void* args)
    {
        Intent* intent = static_cast<Intent*>(args);
        pthread_detach(pthread_self());
        intent->_tcp->Service(intent->_sockfd,intent->_addr);
        delete intent;
        return nullptr;
    }
    void Run()
    {
        _isruning = true;
        while (_isruning)
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            // 建立连接,类似于饭店拉客，客户拒绝了还可以继续拉其他客户
            int sockfd = accept(_listensockfd, (struct sockaddr *)&peer, &len);
            if (sockfd < 0)
            {
                LOG(LogLevel::WARNING) << "accept error";
                continue;
            }

            //
            InetAddr addr(peer);
            LOG(LogLevel::DEBUG) << "accept success, addr:" << addr.GetName();


            // //1.多进程版
            // pid_t id = fork();
            // if(id ==0)
            // {
            //     //关闭孙子进程的监听，只需要进行处理消息就行
            //     close(_listensockfd);
            //     //子
            //     if(fork()>0)//创建孙子，让孙子进程去处理任务，关闭子
            //     exit(OK);
            //     Service(sockfd,addr);
            //     exit(OK);

            // }
            // else
            // {
            //     close(sockfd);
            //     waitpid(id,nullptr,0);
            // }
            //2.多线程版
            Intent* in = new Intent(addr,sockfd,this);
            pthread_t tid;
            pthread_create(&tid,nullptr,Router,in);


        }
        _isruning=false;
    }
    ~Tcpserver()
    {
    }

private:
    uint16_t _port;
    int _listensockfd;
    bool _isruning;
};